package com.samehope.ar.service.impl;

import com.samehope.ar.constant.DelFlagEnum;
import com.samehope.ar.constant.RoleNameEnum;
import com.samehope.ar.dto.TeamMemberAddParam;
import com.samehope.ar.dto.TeamMemberUpdateParam;
import com.samehope.ar.entity.*;
import com.samehope.ar.mapper.ProjectTeamMemberMapper;
import com.samehope.ar.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.samehope.ar.util.SessionUtil;
import com.samehope.ar.vo.FormSelectVO;
import com.samehope.ar.vo.TeamMemberVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 项目团队成员 服务实现类
 * </p>
 *
 * @author Zhang Luo
 * @since 2019-12-23
 */
@Service
public class ProjectTeamMemberServiceImpl extends ServiceImpl<ProjectTeamMemberMapper, ProjectTeamMember> implements IProjectTeamMemberService {

    @Autowired
    private ISysUserRoleService userRoleService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private ISysUserCompanyService userCompanyService;

    @Autowired
    private ITaskNormalService taskNormalService;

    @Autowired
    private IPatrolTaskPlanService taskPlanService;

    /**
     * 添加 项目/团队 成员
     * @param param
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(TeamMemberAddParam param) {

        final LocalDateTime now = LocalDateTime.now();

        final SysRole employeeRole = roleService.findByRoleName(RoleNameEnum.EMPLOYEE.getName());

        final SysRole memberRole = roleService.findByRoleName(RoleNameEnum.MEMBER.getName());

        final SysRole teamRole = roleService.findByRoleName(RoleNameEnum.TEAM.getName());

        SysUser srcUser = userService.getByMobile(param.getMobile());

        if (srcUser == null) {
            // 如果用户不存在
            srcUser = new SysUser();
            srcUser.setMobile(param.getMobile());
            srcUser.setName(param.getName());
            srcUser.setCompanyId(SessionUtil.getCompanyId());
            srcUser.setStatus(0);
            srcUser.setCreateBy(SessionUtil.getUserId());
            srcUser.setCreateDate(now);
            userService.save(srcUser);
        } else {
            // 判断是否已经存在项目成员关系
            ProjectTeamMember teamMember = this.baseMapper.findByProjectAndUser(SessionUtil.getProjectId(), srcUser.getId());
            if (teamMember != null) {
                throw new IllegalArgumentException("成员已存在, 请勿重复添加");
            }
            // 用户姓名发生变更, 更新数据库
            if (!param.getName().equals(srcUser.getName())) {
                srcUser.setName(param.getName());
                srcUser.setCompanyId(SessionUtil.getCompanyId());
                userService.updateById(srcUser);
            }
        }

        // 创建用户角色关系
        List<SysUserRole> userRoles = new ArrayList<>();

        /*
         * 用户企业关系不存在时, 创建需要的关系对象
         */
        SysUserCompany userCompany = userCompanyService.findByCompanyAndUser(SessionUtil.getCompanyId(), srcUser.getId());
        // 创建用户企业关系对象
        if (userCompany == null) {
            this.saveUserCompany(srcUser.getId(), now);

            // 企业员工角色
            SysUserRole employeeUserRole = userRoleService.createObject(srcUser.getId(), employeeRole.getId(), now);
            employeeUserRole.setProjectId(null);
            userRoles.add(employeeUserRole);
        }

        // 项目成员角色
        SysUserRole memberUserRole = userRoleService.createObject(srcUser.getId(), memberRole.getId(), now);
        userRoles.add(memberUserRole);

        // 是否存在勾选的管理角色
        int isManage = 0;
        if (param.getRoleIds() != null && param.getRoleIds().size() > 0) {
            List<Long> roleIds = param.getRoleIds();
            for (Long roleId : roleIds) {
                SysUserRole var = userRoleService.createObject(srcUser.getId(), roleId, now);
                userRoles.add(var);
            }
            // 判断是否团队管理员
            if (roleIds.contains(teamRole.getId())) {
                isManage = 1;
            }
        }

        // 保存角色
        userRoleService.saveBatch(userRoles);

        // 保存团队成员关系
        this.saveTeamMember(srcUser.getId(), param.getTeamId(), now, isManage);
    }

    /**
     * 修改 项目/团队 成员关系
     * @param param
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void update(TeamMemberUpdateParam param) {

        final LocalDateTime now = LocalDateTime.now();

        // 如果用户姓名被更改, 则更新数据库
        SysUser sysUser = userService.getById(param.getUserId());
        if (!param.getName().equals(sysUser.getName())) {
            sysUser.setName(param.getName());
            sysUser.setUpdateBy(SessionUtil.getUserId());
            sysUser.setUpdateDate(now);
            userService.updateById(sysUser);
        }

        Long teamId = param.getTeamId() == null ? -1L : param.getTeamId();

        ProjectTeamMember teamMember = this.baseMapper.findByProjectAndUser(SessionUtil.getProjectId(), param.getUserId());

        // 处理团队变更
        if (!teamId.equals(teamMember.getTeamId())) {
            teamMember.setTeamId(teamId);
            teamMember.setUpdateBy(SessionUtil.getUserId());
            teamMember.setUpdateDate(now);
            this.updateById(teamMember);
        }

        // 处理用户角色
        List<SysUserRole> manageUserRoles = userRoleService.findManageUserRole(param.getUserId());
        List<Long> roleIds = param.getRoleIds();

        if (roleIds == null || roleIds.size() == 0) {
            // 如果管理员角色存在, 并被清空, 那就删除所有管理员角色
            if (manageUserRoles.size() > 0) {
                manageUserRoles.forEach(e -> {
                    e.setDelFlag(DelFlagEnum.DELETED.getCode());
                    e.setUpdateBy(SessionUtil.getUserId());
                    e.setUpdateDate(now);
                });
                userRoleService.updateBatchById(manageUserRoles);
            }
        } else {
            List<SysUserRole> addUserRoles = new ArrayList<>();
            List<SysUserRole> delUserRoles = new ArrayList<>();
            if (manageUserRoles.size() == 0) {
                // 如果原来没有管理员角色, 新增
                for (Long roleId : roleIds) {
                    SysUserRole var = userRoleService.createObject(param.getUserId(), roleId, now);
                    addUserRoles.add(var);
                }
                userRoleService.saveBatch(addUserRoles);
            } else {
                // 获取原有管理员角色
                List<Long> srcRoleIds = manageUserRoles.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
                // 如果原来没有管理员角色, 新增
                for (Long roleId : roleIds) {
                    if (!srcRoleIds.contains(roleId)) {
                        SysUserRole var = userRoleService.createObject(param.getUserId(), roleId, now);
                        addUserRoles.add(var);
                    }
                }

                // 如果删除的管理员角色需要删除
                for (SysUserRole userRole : manageUserRoles) {
                    if (!roleIds.contains(userRole.getRoleId())) {
                        userRole.setDelFlag(DelFlagEnum.DELETED.getCode());
                        userRole.setUpdateBy(SessionUtil.getUserId());
                        userRole.setUpdateDate(now);
                        delUserRoles.add(userRole);
                    }
                }

                if (addUserRoles.size() > 0) {
                    userRoleService.saveBatch(addUserRoles);
                }

                if (delUserRoles.size() > 0) {
                    userRoleService.updateBatchById(delUserRoles);
                }
            }

        }
    }

    /**
     * 从项目中删除该用户
     * Tips: 虽然从项目中删除了, 但是该用户还存在企业中
     * @param userId
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(Long userId) {

        final LocalDateTime now = LocalDateTime.now();

        ProjectTeamMember teamMember = this.baseMapper.findByProjectAndUser(SessionUtil.getProjectId(), userId);
        if (teamMember == null) {
            throw new IllegalArgumentException("项目中无该用户");
        }

        List<TaskNormal> taskNormals = taskNormalService.findTaskNormalByUserNotOver(userId);
        if (taskNormals.size() > 0) {
            throw new IllegalArgumentException("该用户有未结束的计划, 不能删除");
        }

        List<PatrolTaskPlan> taskPlans = taskPlanService.findTaskPlanByUser(userId);
        if (taskPlans.size() > 0) {
            throw new IllegalArgumentException("该用户有计划任务, 不能删除");
        }


        teamMember.setDelFlag(DelFlagEnum.DELETED.getCode());
        teamMember.setUpdateBy(SessionUtil.getUserId());
        teamMember.setUpdateDate(now);
        this.updateById(teamMember);

        // 清空所有项目的角色
        List<SysUserRole> userRoles = userRoleService.findRolesByUser(userId);
        userRoles.forEach(e -> {
            e.setDelFlag(DelFlagEnum.DELETED.getCode());
            e.setUpdateBy(SessionUtil.getUserId());
            e.setUpdateDate(now);
        });

        // 项目角色肯定存在, 至少存在项目成员角色, 所以无需判空, 如果报错, 代表业务逻辑异常, 需要排查
        userRoleService.updateBatchById(userRoles);
    }

    /**
     * 根据团队获取项目成员列表
     * @param teamId
     * @return
     */
    @Override
    public List<TeamMemberVO> members(Long teamId) {
        return this.baseMapper.findMembersByProjectAndTeam(SessionUtil.getProjectId(), teamId);
    }

    /**
     * 获取团队成员下拉框数据
     * @return
     */
    @Override
    public List<FormSelectVO> listForSelect() {
        return this.baseMapper.listForSelectByProject(SessionUtil.getProjectId());
    }

    /**
     * 保存用户公司关系
     * @param userId
     * @param createDate
     */
    private void saveUserCompany(Long userId, LocalDateTime createDate) {
        SysUserCompany userCompany = new SysUserCompany();
        userCompany.setUserId(userId);
        userCompany.setCompanyId(SessionUtil.getCompanyId());
        userCompany.setIsManage(0);
        userCompany.setCreateBy(SessionUtil.getUserId());
        userCompany.setCreateDate(createDate);
        userCompanyService.save(userCompany);
    }

    /**
     * 保存团队成员关系
     * @param userId
     * @param teamId
     * @param createDate
     * @param isManage
     */
    private void saveTeamMember(Long userId, Long teamId, LocalDateTime createDate, Integer isManage) {
        ProjectTeamMember teamMember = new ProjectTeamMember();
        teamMember.setCompanyId(SessionUtil.getCompanyId());
        teamMember.setProjectId(SessionUtil.getProjectId());
        teamMember.setTeamId(teamId == null ? -1L : teamId);
        teamMember.setMemberBy(userId);
        teamMember.setIsManage(isManage);
        teamMember.setCreateBy(SessionUtil.getUserId());
        teamMember.setCreateDate(createDate);
        this.save(teamMember);
    }
}
